#include "client.h"
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <strings.h>
#include <crypt.h>

typedef struct shareRes_s{
    char ip[64];
    char port[16];
    tlv_msg_t token;
    stdin_msg_t stdin_msg;
} shareRes_t;

void *threadFunc(void *arg){
    shareRes_t *pshareRes = (shareRes_t *)arg;
    int netfd = tcpInit(pshareRes->ip, pshareRes->port);
    if (netfd > 0) {
        // 发送 token
        tlv_send(netfd, &pshareRes->token);
        // 执行命令
        stdinCommand(netfd, pshareRes->stdin_msg);
        close(netfd);
    } else {
        printf("无法连接到服务器 %s:%s\n", pshareRes->ip, pshareRes->port);
    }
    return 0;
}

int main(int argc,char* argv[])
{
    ARGS_CHECK(argc,3);
    
    //函数定义
    char directive[100]; //直接输入的命令
    char command[50] = {0}; //命令
    char parameter[256] = {0}; //命令后参数
    int num;
    tlv_msg_t msg;
    stdin_msg_t stdin_msg;
    char buff[1024]; 
    char curPath[100] = "/"; //当前的路径
    tlv_msg_t user_msg;
    tlv_msg_t password_msg;
    tlv_msg_t recv_msg;
    tlv_msg_t ready_msg;
    int sockfd = tcpInit(argv[1],argv[2]);
    while (1) {
        char choice[16];
        bzero(&user_msg, sizeof(tlv_msg_t));
        bzero(&password_msg, sizeof(tlv_msg_t));
        bzero(&recv_msg, sizeof(tlv_msg_t));
        bzero(&ready_msg, sizeof(tlv_msg_t));
        printf("请选择操作: 登录:1  注册:2\n");  //用户选择登录或注册
        if (fgets(choice, sizeof(choice), stdin) == NULL) {
            if (feof(stdin)) {
                close(sockfd);
                exit(0);
            }
            continue;
        }
        choice[strcspn(choice, "\n")] = 0;

        if (strcmp(choice, "1") == 0 || strcasecmp(choice, "login") == 0) {   //用户选择登录
            printf("请输入用户名：");
            char username[50];
            if (fgets(username, sizeof(username), stdin) == NULL) {
                if (feof(stdin)) { close(sockfd); exit(0); }
                continue;
            }
            username[strcspn(username, "\n")] = 0; // 去除换行符

            printf("请输入密码：");
            char password[50];
            if (fgets(password, sizeof(password), stdin) == NULL) {
                if (feof(stdin)) { close(sockfd); exit(0); }
                continue;
            }
            password[strcspn(password, "\n")] = 0; // 去除换行符
            tlv_create(&user_msg, DO_LOGIN, strlen(username), username);
            tlv_send(sockfd, &user_msg);
            tlv_recv(sockfd, &recv_msg);
            if(recv_msg.hdr.type == LOGIN_FALSE) {
                printf("%s\n", recv_msg.value);
                continue; // 用户名不存在，重新输入
            }else if(recv_msg.hdr.type == LOGIN_IN) {
                char crypted_password[128] = {0};
            
                memcpy(crypted_password,crypt(password,recv_msg.value),strlen(crypt(password,recv_msg.value)));
                bzero(&recv_msg, sizeof(tlv_msg_t));
                tlv_create(&password_msg, DO_LOGIN, strlen(crypted_password), crypted_password);
                tlv_send(sockfd, &password_msg);
                tlv_recv(sockfd, &recv_msg);
            }else{
                printf("%s\n", recv_msg.value);
                break; // 用户名不存在，重新输入
            }
            if (recv_msg.hdr.type == LOGIN_IN) {
                printf("%s\n", recv_msg.value);
                break; // 认证成功
            } else if (recv_msg.hdr.type == LOGIN_FALSE) {
                printf("%s\n", recv_msg.value);
                printf("请重新输入用户名和密码进行认证。\n");
                continue;
            } else {
                if (recv_msg.value && strlen(recv_msg.value) > 0) printf("%s\n", recv_msg.value);
                continue;
            }

        } else if (strcmp(choice, "2") == 0 || strcasecmp(choice, "register") == 0) {  //用户选择注册
            printf("请输入注册的用户名：");
            char username[50];
            if (fgets(username, sizeof(username), stdin) == NULL) {
                if (feof(stdin)) { close(sockfd); exit(0); }
                continue;
            }
            username[strcspn(username, "\n")] = 0;

            printf("请输入注册的密码：");
            char password[50];
            if (fgets(password, sizeof(password), stdin) == NULL) { 
                if (feof(stdin)) { close(sockfd); exit(0); }
                continue;
            }
            password[strcspn(password, "\n")] = 0;
            tlv_create(&ready_msg, DO_REGISTER, strlen(username), username);
            tlv_create(&user_msg, DO_REGISTER, strlen(username), username);
            tlv_create(&password_msg, DO_REGISTER, strlen(password), password);
            tlv_send(sockfd, &ready_msg);
            tlv_send(sockfd, &user_msg);
            tlv_send(sockfd, &password_msg);
            tlv_recv(sockfd, &recv_msg);
            if (recv_msg.hdr.type == LOGIN_IN) {
                printf("%s\n", recv_msg.value);
                continue; 
            } else if (recv_msg.hdr.type == LOGIN_FALSE) {
                printf("%s\n", recv_msg.value);
                continue;
            } else {
                if (recv_msg.value && strlen(recv_msg.value) > 0) printf("%s\n", recv_msg.value);
                continue;
            }

        } else {
            printf("输入有误，请输入 1 或 2\n");
            continue;
        }
    }
    bzero(&recv_msg, sizeof(tlv_msg_t));
    tlv_recv(sockfd, &recv_msg); // 接收登录成功后服务器发送的 token

    printf("=== 登录成功！欢迎进入小9窝的网盘系统 ===\n");
    printf("cd：进入对应目录\n");
    printf("ls：列出相应目录文件\n");
    printf("pwd：显示当前文件的绝对路径\n");
    printf("puts：将本地文件上传到服务器\n");
    printf("gets：将服务器文件下载到本地\n");
    printf("mkdir：在服务器中创建文件夹\n");
    printf("rmdir：移除服务器中的指定文件夹\n");
    printf("close：注销用户\n");
    printf("quit：退出程序\n");

    while(1)
    {
        printf("[小9窝]> ");
        fflush(stdout);
        
        // 清空缓冲区
        bzero(directive, sizeof(directive));
        bzero(command, sizeof(command));
        bzero(parameter, sizeof(parameter));
        bzero(&msg, sizeof(tlv_msg_t));
        bzero(buff, sizeof(buff));
        bzero(&stdin_msg, sizeof(stdin_msg_t));

        // 读取用户输入
        if (fgets(directive, sizeof(directive), stdin) == NULL) {
            if (feof(stdin)) {
                printf("\n检测到EOF，退出程序\n");
                close(sockfd);
                exit(0);
            }
            continue;
        }

        // 移除换行符
        directive[strcspn(directive, "\n")] = 0;

        // 跳过空行
        if (strlen(directive) == 0) {
            continue;
        }

        // 解析命令和参数
        char *first_token = strtok(directive, " ");
        if (first_token != NULL) {
            strncpy(command, first_token, sizeof(command) - 1);
            command[sizeof(command) - 1] = '\0';
            
            // 获取剩余部分作为参数
            char *remainder = strtok(NULL, "");
            if (remainder != NULL) {
                // 去除参数前导空格
                while (*remainder == ' ') {
                    remainder++;
                }
                if (strlen(remainder) > 0) {
                    strncpy(parameter, remainder, sizeof(parameter) - 1);
                    parameter[sizeof(parameter) - 1] = '\0';
                }
            }
        }

        num = enumInt(command);
        if (num == -1) {
            printf("未知命令: %s\n", command);
            continue;
        }
        
        int param_length = 0;
        const char *param_value = "";
        
        if (strlen(parameter) > 0) {
            param_length = strlen(parameter);
            param_value = parameter;
        }
        
        // ls命令如果没有参数，默认使用当前路径
        if (num == CMD_LS && param_length == 0) {
            param_length = strlen(curPath);
            param_value = curPath;
        }
        
        
        stdin_msg.type = num;
        strncpy(stdin_msg.value, param_value, param_length);
        stdin_msg.value[param_length] = '\0';
        
         if(num == CMD_PUTS_REQ || num == CMD_GETS_REQ) {
            shareRes_t  shareRes;
            memset(&shareRes, 0, sizeof(shareRes_t));
            strcpy(shareRes.ip, argv[1]);
            strcpy(shareRes.port, argv[2]);
            memcpy(&shareRes.token, &recv_msg, sizeof(tlv_msg_t)); // 保存登录时收到的 token
            memcpy(&shareRes.stdin_msg, &stdin_msg, sizeof(stdin_msg_t)); // 保存要执行的命令和参数
            pthread_t tid;
            pthread_create(&tid, NULL, threadFunc,&shareRes);
            pthread_join(tid, NULL);
        } else {
            stdinCommand(sockfd,stdin_msg);// 处理用户输入的命令
        }
        
       if (num == CMD_CD && strlen(parameter) > 0) {
            // 更新当前路径
            if (parameter[0] == '/') {
                // 绝对路径
                strncpy(curPath, parameter, sizeof(curPath) - 1);
                curPath[sizeof(curPath) - 1] = '\0';
            } else {
                // 相对路径
                if (strcmp(parameter, "..") == 0) {
                    // 返回上一级目录
                    char *last_slash = strrchr(curPath, '/');
                    if (last_slash != NULL && last_slash != curPath) {
                        *last_slash = '\0';
                    } else {
                        // 已经在根目录，保持不变
                        strcpy(curPath, "/");
                    }
                } else {
                    // 进入子目录
                    if (strcmp(curPath, "/") != 0) {
                        strncat(curPath, "/", sizeof(curPath) - strlen(curPath) - 1);
                    }
                    strncat(curPath, parameter, sizeof(curPath) - strlen(curPath) - 1);
                }
            }
        } 
    }
    close(sockfd);
    return 0;
}
